#include<bits/stdc++.h>

#define esp 1e-10
int sign(double x) {
    if (fabs(x) < esp) return 0;
    if (x > 0) return 1;
    return -1;
}
template<class T = double>
struct po {
    T x, y;
    void rd() {
        cin >> x >> y;
    }
    po(){}
    po(T x_, T y_) : x(x_), y(y_){}

    template<class U>
    operator po<U>() {
        return po<U>(U(x), U(y));
    }

    po operator+(const po& t) const {
        return {x + t.x, y + t.y};
    } 
    po operator-(const po& t) const {
        return {x - t.x, y - t.y};
    }
    po operator+(T v) const {
        return {x + v, y + v};
    }
    po operator*(T v) const {
        return {x * v, y * v};
    }
    po operator-(T v) const {
        return {x - v, y - v};
    }
    T operator*(const po& t) const {
        return x * t.y - y * t.x;
    }
    void show() {
        db(x, y);
    }
};

template<class T>
T cross(const po<T>& x, const po<T>& y) {
    return x.x * y.y - x.y * y.x;
}
template<class T>
T dot(const po<T>& x, const po<T>& y) {
    return x.x * y.x + x.y * y.y;
}

template<class T>
vector<po<T>> Andrew (vector<po<T>> a) {
    int n = a.size();
    sort(a.begin(), a.end(), [&] (po<T> x, po<T> y) {
        return (x.x == y.x ? x.y < y.y : x.x < y.x);
    });

    vector<int> st(n * 2 + 10); int top = 0;
    for(int i = 1; i < n; i++) {
        while(top > 0 && cross(a[i] - a[st[top]], a[st[top]] - a[st[top - 1]]) >= 0) top--; 
        st[++top] = i;
    }
    int t = top;
    for(int i = n - 2; i >= 0; i--) {
        while(top > t && cross(a[i] - a[st[top]], a[st[top]] - a[st[top - 1]]) >= 0) top--; 
        st[++top] = i;
    }
    vector<po<T>> ans;
    for (int i = 0; i < top; i++) {
        ans.push_back(a[st[i]]);
    }
    return ans;
}

struct Line {
    po<double> s, e;

    double angle() const {
        return atan2(e.y - s.y, e.x - s.x);
    }
    bool operator<(const Line& t) const {
        double a = angle(), ta = t.angle();
        return sign(a - ta) == 0 ? cross(e - s, t.e - s) < 0 : a < ta;
    }
    void show() {
        cout << "---\n";
        s.show(), e.show();
        cout << "---\n";
    }
};
po<double> cross(Line a, Line b) {
    po u = a.s - b.s, v = a.e - a.s, w = b.e - b.s;
    double t = 1.0 * (u * w) / (w * v);
    po tmp = a.s;
    return (tmp) + (v) * t;
}
bool inright(Line x, Line a, Line b) {
    return cross(x.e - x.s, cross(a, b) - x.s) < 0;
}

/*
半平面交模板，输入有限直线序列，返回面积，有向直线用两个点表示s->e
算法流程：1.按照斜率排序  2.加入直线删队尾、队头  3.用队头去除尾巴
*/
double haftplane(vector<Line> a) {
    sort(a.begin(), a.end());

    int n = a.size();
    vector<Line> q(n + 3); int h = 0, t = 0;
    q[0] = a[0];
    for (int i = 1; i < n; i++) {
        if (sign(a[i].angle() - a[i - 1].angle()) == 0) continue;
        while (h < t && inright(a[i], q[t], q[t - 1])) t--;
        while (h < t && inright(a[i], q[h], q[h + 1])) h++;
        q[++t] = a[i];
    }
    while (h < t && inright(q[h], q[t], q[t - 1])) t--;
    q[++t] = q[h];  

    vector<po<double>> p;
    for (int i = h; i < t; i++) p.push_back({cross(q[i], q[i + 1])});

    double res = 0;
    for (int i = 1; i + 1 < p.size(); i++) {
        res += (p[i] - p[0]) * (p[i + 1] - p[0]);
    }
    return res / 2;
};